package server;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebAppClassLoader extends ClassLoader {
    private String classpath;
    private  Map<String,byte[]> classMap = new ConcurrentHashMap<>();

    public WebAppClassLoader() {
        super();
    }

    public WebAppClassLoader(String classpath) {
        if(classpath.endsWith(File.separator)) {
            this.classpath = classpath;
        }else{
            this.classpath = classpath + File.separator;
        }
        preReadClassFile();
    }

    private void preReadClassFile() {
        File[] files = new File(classpath).listFiles();
        if (files != null) {
            for (File file : files) {
                scanClassFile(file);
            }
        }
    }

    private void scanClassFile(File file) {
        if(file.exists()){
            if(file.isFile() && file.getName().endsWith(".class")){
                try{
                    byte[] byteCode = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
                    String className = file.getAbsolutePath().replace(classpath,"")
                            .replace(File.separator,".")
                            .replace(".class","");
                    addClass(className,byteCode);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }else if (file.isDirectory()){
                for(File f : file.listFiles()){
                    scanClassFile(f);
                }
            }
        }

    }

    private  boolean addClass(String className,byte[] classCode) {
        if(!classMap.containsKey(className)){
            classMap.put(className,classCode);
            return true;
        }
        return false;
    }


    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            //全限定类名
            byte[] result = getClass(name);
            if (result == null) {
                throw new ClassNotFoundException();
            } else {
                return defineClass(name, result, 0, result.length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    private byte[] getClass(String className) {
        if (classMap.containsKey(className)) {
            return classMap.get(className);
        } else {
            return null;
        }

    }
}
